home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 076-100 / 087 / dropshadow / ds.c < prev    next >
C/C++ Source or Header  |  1995-03-13  |  12KB  |  538 lines

  1. /** dropshadow.c **/
  2.  
  3. /* this program copyright 1987, james mackraz.  may not be distributed
  4.  * for profit.  copies of the source may be made for not-for-profit
  5.  * distribution, but must include this notice.
  6.  *
  7.  * james mackraz, 4021 Second Street, Palo Alto, CA, 94306
  8.  */
  9.  
  10. #include "ds.h"
  11. #include <tools/debug.h>
  12.  
  13. #define printf  kprintf
  14.  
  15. UBYTE    *wtitle    = (UBYTE *) "  DropShadow -- ver 2, rev 0  ";
  16. struct  Window      *getNewWind();
  17.  
  18. struct RastPort    *rport2 = NULL;    /* for rendering into bmap2    */
  19. struct Window   *window = NULL;
  20.  
  21. struct    Task    *mytask;
  22. UBYTE            mysig = 0;
  23.  
  24. struct  IntuitionBase   *IntuitionBase;
  25. struct  GfxBase         *GfxBase;
  26. struct    LayersBase        *LayersBase;
  27.  
  28. ULONG   flg = ACTIVATE | WINDOWCLOSE | NOCAREREFRESH | WINDOWDRAG
  29.         | WINDOWDEPTH | SIMPLE_REFRESH;
  30.  
  31. ULONG   iflg = MOUSEMOVE | CLOSEWINDOW | GADGETDOWN | GADGETUP;
  32.  
  33. /* for each layer, front to back, not incl. backdrops    */
  34. #define FORLAYERS(l, linfo)    for (l = (linfo)->top_layer; \
  35.      l && !(l->Flags & LAYERBACKDROP);l=l->back)
  36.  
  37. #define BACKTOFRONT(l)     for (l = window->WLayer->LayerInfo->top_layer;    \
  38. l && l->back; l = l->back) ; \
  39. for (; l; l = l->front)
  40.  
  41. #define PREDLAYERS(pred, l) for (pred = l->front; pred; pred = pred->front)
  42.  
  43. #define MYPRI             7L    /* a little advantage                        */
  44. #define INPUTPRI_PLUS    25L    /* i guess i could findtask("input.device")    */
  45.  
  46. USHORT    hdrop = 7;
  47. USHORT    vdrop = 3;
  48.  
  49. main()
  50. {
  51.     struct  IntuiMessage    *msg;
  52.  
  53.     /* hold data from *msg  */
  54.     ULONG   class;
  55.     UBYTE   code;
  56.     struct Gadget *gaddress;
  57.  
  58.     struct Screen    *wbscreen;
  59.     struct BitMap    *save_bitmap= NULL;    /* original WB RasInfo bitmap    */
  60.     struct BitMap    *ribitmap    = NULL;        /* my 3-deep replacement        */
  61.     struct BitMap      *bmap2        = NULL;
  62.  
  63.     int        i;
  64.     int        it_is_done = 0;        /* success flag            */
  65.     WORD    exitval = 0;
  66.     ULONG    sigmask;
  67.     ULONG    sigtaken;
  68.  
  69.     extern struct PropInfo twxtinfo;
  70.     USHORT    twxtpot;
  71.  
  72.     if (!(IntuitionBase = (struct IntuitionBase *)
  73.         OpenLibrary("intuition.library", 0L)))
  74.     {
  75.         D( printf("NO INTUITION LIBRARY\n") );
  76.         exitval = 1;
  77.         goto EXITING;
  78.     }
  79.  
  80.     if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
  81.     {
  82.         D( printf("NO GRAPHICS LIBRARY\n") );
  83.         exitval = 2;
  84.         goto EXITING;
  85.     }
  86.  
  87.     if (!(LayersBase=(struct LayersBase *) OpenLibrary("layers.library", 0L)))
  88.     {
  89.         D( printf("NO LAYERS LIBRARY\n") );
  90.         exitval = 2;
  91.         goto EXITING;
  92.     }
  93.  
  94.     /* get a window on the workbench    */
  95.     window = getNewWind(120, 20, 400, 30, flg, iflg);
  96.     if (window == NULL)
  97.     {
  98.         D( printf("test: can't get window.\n") );
  99.         exitval = 1;
  100.         goto EXITING;
  101.     }
  102.  
  103.     /* Add bitplane to the Workbench, as far as ViewPort is concerned    */
  104.  
  105.     wbscreen = window->WScreen;        /* find it    */
  106.  
  107.     /* new 3-deep bitmap will replace the one in WB's RInfo    */
  108.     if (!(ribitmap = (struct BitMap *)
  109.         AllocMem((LONG) sizeof(struct BitMap), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
  110.     {
  111.         D( printf("alloc bitmap failed\n") );
  112.         goto EXITING;
  113.     }
  114.     InitBitMap(ribitmap, 3L, (LONG) wbscreen->Width, (LONG) wbscreen->Height);
  115.  
  116.     /* allocate bitmap for my rastport view of single bitplane    */
  117.     if (!(bmap2 = (struct BitMap *)
  118.         AllocMem((LONG) sizeof(struct BitMap), (LONG) MEMF_PUBLIC|MEMF_CLEAR)))
  119.     {
  120.         D( printf("alloc bitmap failed\n") );
  121.         goto EXITING;
  122.     }
  123.  
  124.     /* my rendering bit map: depth 1    */
  125.     InitBitMap(bmap2, 1L, (LONG) wbscreen->Width, (LONG) wbscreen->Height);
  126.  
  127.     if (!(bmap2->Planes[0] =
  128.         (UBYTE *) AllocRaster((LONG) wbscreen->Width, (LONG) wbscreen->Height)))
  129.     {
  130.         D( printf("alloc raster failed\n") );
  131.         goto EXITING;
  132.     }
  133.  
  134.     /* get a rastport, and set it up for rendering into bmap2    */
  135.     if (!(rport2 = (struct RastPort *)
  136.         AllocMem((LONG) sizeof (struct RastPort), (LONG) MEMF_PUBLIC)))
  137.     {
  138.         D( printf("alloc rastport failed\n") );
  139.         goto EXITING;
  140.     }
  141.     InitRastPort(rport2);
  142.     rport2->BitMap = bmap2;
  143.  
  144.     SetRast(rport2, 0L);
  145.  
  146.     /* set up new bitmap for RInfo    */
  147.     save_bitmap =  wbscreen->ViewPort.RasInfo->BitMap;
  148.     ribitmap->Planes[0] = save_bitmap->Planes[0];
  149.     ribitmap->Planes[1] = save_bitmap->Planes[1];
  150.     ribitmap->Planes[2] = bmap2->Planes[0];
  151.  
  152.     Forbid();
  153.  
  154.     /* add our extra plane to the bit-map as viewed by
  155.      * the WB ViewPort (WB should never know the difference)
  156.      */
  157.     wbscreen->ViewPort.RasInfo->BitMap = ribitmap;
  158.  
  159.     Permit();
  160.  
  161.     it_is_done = 1;
  162.  
  163.     shadowColors(wbscreen);
  164.  
  165.     /* put viewport changed into effect    */
  166.     MakeScreen(wbscreen);
  167.     RethinkDisplay();
  168.  
  169.     twxtpot = twxtinfo.HorizPot;
  170.     hdrop = twxtpot >> TWXTSHIFT;
  171.     vdrop = twxtpot >> (TWXTSHIFT + 1);
  172.     drawShadow();
  173.  
  174.     /* hook into the library vectors    */
  175.     mytask = FindTask(0L);
  176.     mysig  = AllocSignal((LONG) -1);
  177.     sigmask = ((LONG) 1 << mysig);
  178.     sigmask |= ((LONG) 1 << window->UserPort->mp_SigBit);
  179.     setup_hooks();
  180.  
  181.     /* a little help    */
  182.     SetTaskPri(mytask, MYPRI);
  183.  
  184.     FOREVER
  185.     {
  186.         if ((msg = (struct IntuiMessage *)GetMsg(window->UserPort)) == NULL)
  187.         {
  188.             sigtaken = Wait(sigmask);
  189.             if (sigtaken & ((LONG) 1 << mysig))
  190.             {
  191.                 drawShadow();
  192.             }
  193.             continue;
  194.         }
  195.  
  196.         class   = msg->Class;
  197.         code    = msg->Code;
  198.         gaddress  = (struct Gadget *) msg->IAddress;
  199.         ReplyMsg(msg);
  200.  
  201.         switch (class)
  202.         {
  203.         case MOUSEMOVE:        /* taken at higher priority    */
  204.             shadowColors(wbscreen);
  205.             break;
  206.  
  207.         case GADGETDOWN:
  208.             SetTaskPri(mytask, INPUTPRI_PLUS);
  209.             break;
  210.  
  211.         case GADGETUP:
  212.             SetTaskPri(mytask, MYPRI);
  213.  
  214.             switch (gaddress->GadgetID)
  215.             {
  216.             case TWIXTID:
  217.                 twxtpot = twxtinfo.HorizPot;
  218.                 hdrop = twxtpot >> TWXTSHIFT;
  219.                 vdrop = twxtpot >> (TWXTSHIFT + 1);
  220.                 drawShadow();
  221.                 break;
  222.             case DARKID:
  223.                 shadowColors(wbscreen);
  224.                 break;
  225.             }
  226.             break;
  227.  
  228.         case CLOSEWINDOW:
  229.             SetTaskPri(mytask, 0L);
  230.             if (cleanup_hooks()) goto EXITING;
  231.         default:
  232.             D( printf("unknown event: class %lx\n", class) );
  233.         }
  234.     }
  235.  
  236. EXITING:
  237.     /* clean up trick    */
  238.     if (it_is_done)
  239.     {
  240.         Forbid();
  241.         wbscreen->ViewPort.RasInfo->BitMap = save_bitmap;
  242.         Permit();
  243.         MakeScreen(wbscreen);
  244.         RethinkDisplay();
  245.     }
  246.  
  247.     if (mysig) FreeSignal((LONG) mysig);
  248.  
  249.     if (rport2) FreeMem(rport2, (LONG) sizeof (struct RastPort));
  250.     if (bmap2) 
  251.     {
  252.         if (bmap2->Planes[0])
  253.         {
  254.             FreeRaster(bmap2->Planes[0],
  255.                 (LONG) wbscreen->Width, (LONG) wbscreen->Height);
  256.         }
  257.         FreeMem(bmap2, (LONG) sizeof (struct BitMap));
  258.     }
  259.     if (ribitmap) FreeMem(ribitmap, (LONG) sizeof (struct BitMap));
  260.  
  261.     if (window) CloseWindow(window);
  262.     if (GfxBase) CloseLibrary(GfxBase);
  263.     if (LayersBase) CloseLibrary(LayersBase);
  264.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  265.  
  266.     exit (exitval);
  267. }
  268.  
  269. /* returns true if this layer casts a shadow
  270.  * note that menu layer does not cast a shadow
  271.  */
  272. shadowCaster(l)
  273. register struct Layer *l;
  274. {
  275.     extern struct PropInfo darkinfo;
  276.     register struct Window        *w;
  277.     register struct RastPort    *brp;
  278.  
  279.     if (l && (w = (struct Window *) l->Window))
  280.     {
  281.         /* must be border layer for GZZ window    */
  282.         if (brp = w->BorderRPort)
  283.         {
  284.             /* GZZ    */
  285.             return (brp->Layer == l);
  286.         }
  287.         else
  288.         {
  289.             /* non-GZZ    */
  290.             return (l == w->WLayer);
  291.         }
  292.     }
  293.     return (0);
  294. }
  295.  
  296. /* called by my replacement layers vectors    */
  297. drawShadowSignal(sysret)
  298. LONG    sysret;
  299. {
  300.     Signal( mytask, ((LONG) 1 << mysig));
  301.     return (sysret);
  302. }
  303.  
  304. /* run on my own task's schedule    */
  305. drawShadow(sysret)
  306. LONG    sysret;
  307. {
  308.     struct Region    *shadow;
  309.  
  310.     if ( !(shadow = NewRegion()) ) return (sysret);
  311.  
  312.     bigShadow(shadow);
  313.  
  314.     SetRast(rport2, 0L);
  315.  
  316.     Forbid();
  317.     WaitBOVP(&window->WScreen->ViewPort);
  318.  
  319.     SetAPen(rport2, 1L);
  320.     fillRegion(rport2, shadow);
  321.     Permit();
  322.  
  323.     DisposeRegion(shadow);
  324. }
  325.  
  326. /* you want speed? speed this up.    */
  327. bigShadow(rgn)
  328. struct    Region    *rgn;
  329. {
  330.     register struct Layer    *pred;    /* pred to 'l'                        */
  331.     register LONG            tmprgn;    /* accumulates shadow on layer 'l'    */
  332.     register struct Layer    *l;        /* create all shadows on each layer    */
  333.  
  334.     int                twixt;        /* number of "spaces" between l, pred    */
  335.     int                htwixt;
  336.     int                vtwixt;
  337.     struct Rectangle lrect;
  338.     struct Rectangle predrect;
  339.  
  340.     if ( !(tmprgn = (LONG) NewRegion()) ) return;
  341.  
  342.     /* protect the integrity of the layer list    */
  343.     LockLayerInfo(window->WLayer->LayerInfo);
  344.  
  345.     BACKTOFRONT(l)
  346.     {
  347.         /* could eliminate any layers you don't want a shadow on here.    */
  348.  
  349.         /* layer rectangle    */
  350.         lrect = l->bounds;
  351.  
  352. #if 0
  353.         notRectRegion(rgn, &lrect);    /* l obscures shadows behind it        */
  354. #else
  355.         ClearRectRegion(rgn, &lrect);    /* dale's version                */
  356. #endif
  357.  
  358. #if OLDTWIXT
  359.         twixt = 0;
  360. #else
  361.         htwixt = hdrop << 1;
  362.         vtwixt = vdrop << 1;
  363. #endif
  364.         ClearRegion(tmprgn);        /* will build shadow on single layer */
  365.  
  366.         /* walk through shadow casters    */
  367.         PREDLAYERS(pred, l)
  368.         {
  369.             /* menu bar doesn't cast shadow    */
  370.             if (!shadowCaster(pred)) 
  371.             {
  372.                 continue;
  373.             }
  374.  
  375.             /* rectangle will cast shadow                */
  376.             predrect = pred->bounds;    /* layer rect    */
  377.  
  378.             /* shadow offset increases with depth        */
  379. #if OLDTWIXT
  380.             translateRect(&predrect,
  381.                 HDROP + twixt * (HDROP >> 1), VDROP + twixt * (VDROP >> 1));
  382.  
  383.             ++twixt;                /* another level up                    */
  384. #else
  385.             translateRect(&predrect, htwixt, vtwixt);
  386.             htwixt += hdrop;
  387.             vtwixt += vdrop;
  388.  
  389. #endif
  390.             /* add it to accumulated shadow on 'l'        */
  391.             OrRectRegion(tmprgn, &predrect);
  392.         }
  393.  
  394.         /* all shadows on 'l' should actually be on 'l'    */
  395.         AndRectRegion(tmprgn, &lrect);
  396.  
  397.         /* add shadows on l to shadows on layers behind l    */
  398.         OrRegionRegion(tmprgn, rgn);
  399.     }
  400.  
  401.     UnlockLayerInfo(window->WLayer->LayerInfo);
  402.     DisposeRegion(tmprgn);
  403. }
  404.  
  405. /* can use dale's ClearRectRegion    */
  406. #if 0
  407. notRectRegion(rgn, rect)
  408. struct Region        *rgn;
  409. struct Rectangle    *rect;
  410. {
  411.     OrRectRegion(rgn, rect);
  412.     XorRectRegion(rgn, rect);
  413. }
  414. #endif
  415.  
  416. /* this doesn't get use anymore    */
  417. #define GOODRECT(r)    (((r)->MinX < (r)->MaxX) && ((r)->MinY < (r)->MaxY))
  418.  
  419. fillRegion(rp, rgn)
  420. struct RastPort    *rp;
  421. struct Region    *rgn;
  422. {
  423.     register struct    RegionRectangle    *rgnrect;
  424.     register struct    Rectangle    *bds;
  425.  
  426.     register int        minx;        /* offsets for all region rectangles    */
  427.     register int        miny;
  428.  
  429.     minx = rgn->bounds.MinX;
  430.     miny = rgn->bounds.MinY;
  431.     rgnrect = rgn->RegionRectangle;
  432.  
  433.     while (rgnrect)
  434.     {
  435.         bds = &rgnrect->bounds;
  436.         RectFill(rp,
  437.             (LONG)minx + bds->MinX,
  438.             (LONG) miny + bds->MinY, 
  439.             (LONG) minx + bds->MaxX,
  440.             (LONG) miny + bds->MaxY);
  441.  
  442.         rgnrect = rgnrect->Next;
  443.     }
  444. }
  445.  
  446. translateRect(r, dx, dy)
  447. register struct    Rectangle *r;
  448. register int        dx;
  449. register int        dy;
  450. {
  451.     r->MinX    += dx;
  452.     r->MaxX    += dx;
  453.     r->MinY    += dy;
  454.     r->MaxY    += dy;
  455. }
  456.  
  457. screenRect(s, r)
  458. register struct Screen        *s;
  459. register struct Rectangle    *r;
  460. {
  461.     r->MaxX = (r->MinX = s->LeftEdge) + s->Width - 1;
  462.     r->MaxY = (r->MinY = s->TopEdge) + s->Height - 1;
  463. }
  464.  
  465. windowRect(w, r)
  466. register struct Window        *w;
  467. register struct Rectangle    *r;
  468. {
  469.     r->MaxX = (r->MinX = w->LeftEdge) + w->Width - 1;
  470.     r->MaxY = (r->MinY = w->TopEdge) + w->Height - 1;
  471. }
  472.  
  473. struct  Window * getNewWind(left, top, width, height, flg, iflg)
  474. SHORT   left, top, width, height;
  475. ULONG   flg, iflg;
  476. {
  477.     extern struct Gadget darkness;
  478.  
  479.     struct  Window  *OpenWindow();
  480.     struct  NewWindow   nw;
  481.  
  482.     nw.LeftEdge =   (SHORT) left;
  483.     nw.TopEdge  =   (SHORT) top;
  484.     nw.Width    =   (SHORT) width;
  485.     nw.Height   =   (SHORT) height;
  486.     nw.DetailPen    =   (UBYTE) -1;
  487.     nw.BlockPen =   (UBYTE) -1;
  488.     nw.IDCMPFlags   =   (ULONG) iflg;
  489.  
  490.     nw.Flags    =   (ULONG) flg;
  491.  
  492.     nw.FirstGadget  =   (struct Gadget *)   &darkness;
  493.     nw.CheckMark    =   (struct Image *)    NULL;
  494.     nw.Title    =   (UBYTE *)   wtitle;
  495.     nw.Screen   =   (struct Screen *)   NULL;
  496.     nw.BitMap   =   (struct BitMap *)   NULL;
  497.     nw.MinWidth =   (SHORT) 50;
  498.     nw.MinHeight=   (SHORT) 30;
  499.     /* work around bug  */
  500.     nw.MaxWidth =   (SHORT) nw.Width;
  501.     nw.MaxHeight    =   (SHORT) nw.Height;
  502.     nw.Type     =   (USHORT) WBENCHSCREEN;
  503.  
  504.     return ((struct Window *) OpenWindow(&nw));
  505. }
  506.  
  507.  
  508. #define DARKER(c)  (((long) (((c) & 0xF) * (darkpot)) ) >> 16)
  509.  
  510. shadowColors(s)
  511. struct Screen *s;
  512. {
  513.     register int    i;
  514.     register ULONG    rgb;
  515.     ULONG    red, green, blue;
  516.     struct    ColorMap    *cm;
  517.     USHORT    darkpot;
  518.  
  519.     darkpot = darkinfo.HorizPot;
  520.  
  521.     cm = s->ViewPort.ColorMap;
  522.  
  523.     for (i = 0; i < 4; ++i)
  524.     {
  525.         /* get three colors    */
  526.         rgb        = GetRGB4(cm, (LONG) i);
  527.  
  528. #if    0
  529.         rgb = ~rgb;    /* wild colors, not wild enough    */
  530. #endif
  531.  
  532.         blue    = DARKER(rgb);
  533.         green    = DARKER(rgb >>= 4);
  534.         red        = DARKER(rgb >> 4);
  535.         SetRGB4(&s->ViewPort, (LONG) i + 4,(LONG) red,(LONG) green,(LONG) blue);
  536.     }
  537. }
  538.